#include<linux/module>
#include<linux/kernel>
#include<linux/platform_device.h>

int major=11;
int minor=0;
int second_num=1;

struct second_dev{
	
	struct cdev mydev;
	atomic_t openflag;//1可以打开，0就不能打开;
	
	unsigned int sec;
	struct timer_list timer;
}

struct second_dev* pgmydev=NULL;


void second_function(unsigned long arg){
	//在这里面把定时器的秒数增加
	struct second_dev* pgmydev=(struct second_dev*)arg;
	
	pgmydev->sec++;
	mod_timer(&pgmydev->timer,jiffies+HZ*1);
	
}
int second_open(struct inode* pnode,struct file* pfile){
	struct second_dev* pgmydev=NULL;
	pgmydev=(struct second_dev*)(continer_of(pnode->i_cdev,struct second_dev,mydev));
	pfile->private_data=(void*)pgmydev;
	
	if(atomic_dec_and_test(&pgmydev->openflag)){	
		//这里面说明我们的设备是没有人进行打开过的
		//这里就可以进行正确的打开返回零
		pgmydev->timer.expires=jiffies+1*HZ;
		pgmydev->timer.function;
		pgmydev->timer.data=(unsigned long)pgmydev;
		
		add_timer(&pgmydev->timer);
	}else{
		//这里说明已经不是第一次打开了
		atomic_inc(&pgmydev->openflag);
		printk("The device is opened already\n");
		return -1;
	}
	return 0;
}
int second_close(struct inode* pnode,struct file* pfile){
	
	return 0;
}
ssize_t second_read(struct file* pfile,char __user* puser,size_t count,loff_t* p_pos){
	struct second_dev* pgmydev=(struct second_dev*)pfile->private_data;
	unsigned int size=0;
	int ret=0;
	if(count>=sizeof(unsigned int)){
		size=sizeof(unsigned int);
	}else{
		printk("too few\n");
		return -1;
	}
	ret=copy_to_user(puser,&pgmydev->sec,size);
	if(ret){
		
		printk("copy failed\n");
		return -1;
	}
	return size;
}

struct file_operations myops{
	.owner=THIS_MODULE,
	.open=second_open;
	.release=second_close,
	.read=second_read,
}


int __init second_init(void){
	int ret=0;
	dev_t devno=MKDEV(major,minor);
	ret=register_chrdev_region(devno,second_num,"second");
	if(ret){
		
		ret=alloc_chrdev_region(&devno,second_num,"second");
		if(ret){
			printk("register devno failed\n");
			return -1;
		}
		major=MAJOR(devno);
	}
	
	pgmydev=(struct second_dev*)kmalloc(sizeof(struct second_dev),GPF_KERNEL);
	if(NULL==pgmydev){
		
		printk("kmalloc failed\n");
		unregister_chrdev_region(devno,second_num);
		return -1;
	}
	memset(pgmydev,0,sizeof(struct second_dev));
	
	cdev_init(&pgmydev->mydev,&myops);
	pgmydev->mydev.owner=THIS_MODULE;
	
	cdev_add(&pgmydev->mydev,devno,second_num);
	
	
	atomic_set(&pgmydev->openflag,1);
	//在入口函数中进行初始化，加入内核定时器链表开始计数是在open之后
	init_timer(&pgmydev->timer);
	
	return 0;
}

int __exit second_exit(void){
	
	dev_t devno=MKDEV(major,minor);
	unregister_chrdev_region(devno,second_num);
	cdev_del(&pgmydev->mydev);
	del_timer(&pgmydev->timer);
	kfree(pgmydev);
	pgmydev=NULL;
	return 0;
}

MODULE_LICENSE("GPL");
module_init(second_init);
module_exit(second_exit);